package nameless.aistudy.api;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import nameless.aistudy.domain.model.subjects.english.vocabulary.word.Word;
import nameless.aistudy.domain.service.subjects.english.reading.EnglishTranslateAIService;
import nameless.aistudy.domain.service.subjects.english.vocabulary.VocabularyAIService;
import nameless.aistudy.global.advice.BusinessExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.UUID;

@RestController
public class DemoController {

    private final Logger log = LoggerFactory.getLogger(DemoController.class);

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private BusinessExceptionHandler businessExceptionHandler;

    @Autowired
    VocabularyAIService vocabularyAIService;

    private final ChatClient.Builder builder;
//    private final ChatClient chatClient;

    private ChatClient buildChatClient(Double temperature, Integer maxTokens) {
        if (temperature == null) temperature = 1.0;
        if (maxTokens == null) maxTokens = 1024;
        return this.builder
                .defaultOptions(
                        OpenAiChatOptions.builder()
                                .maxTokens(maxTokens)
                                .temperature(temperature)
                                .build()
                )
                .build();
    }


    @Autowired
    public DemoController(ChatClient.Builder builder) {
        this.builder = builder;
//        this.chatClient = builder
//                .defaultOptions(
//                        OpenAiChatOptions.builder()
//                                .temperature(0.0)
//                                .build()
//                )
//                .build();
    }

    //
//    @GetMapping("/ex")
//    public String ex(@RequestParam("ex") String ex) {
//        switch (ex) {
//            case "forbidden": throw BusinessException.forbidden();
//            case "unauthorized": throw BusinessException.unauthorized();
//            case "notFound": throw BusinessException.notFound();
//        }
//        return "OK";
//    }
//
    @GetMapping("/ask")
    public String ask(
            @RequestParam("question") String question,
            @RequestParam(value = "temperature", required = false) Double temperature
    ) {
        ChatClient chatClient = buildChatClient(temperature, null);
        return chatClient.prompt().user(question).call().content();
    }

    @GetMapping("/entity")
    public String entity(
            @RequestParam("question") String question,
            @RequestParam(value = "temperature", required = false) Double temperature,
            @RequestParam(value = "maxTokens", required = false) Integer maxTokens,
            @RequestParam(value = "system", required = false) String systemCommand
    ) throws JsonProcessingException {
        ChatClient chatClient = buildChatClient(temperature, maxTokens);

        record DomainBranches(String domain, String[] branch) {}
        ChatClient.CallResponseSpec callResponse = null;
        if (systemCommand != null) {
            callResponse = chatClient
                    .prompt()
                    .system(systemCommand)
                    .user(question)
                    .call();
        } else {
            callResponse = chatClient
                    .prompt(question)
                    .call();
        }
        try {
            DomainBranches domainBranches = callResponse.entity(DomainBranches.class);
            return objectMapper
                    .writerWithDefaultPrettyPrinter()
                    .writeValueAsString(domainBranches);
        } catch (JsonProcessingException e) {
            return callResponse.content();
        }
    }

    @GetMapping("/word")
    public Word word(
            @RequestParam("spell") String spell
    ) {
        return vocabularyAIService.fillWordBySpell(spell);
    }


    @GetMapping(value = "/ask/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter streamChat(
            @RequestParam("question") String question,
            @RequestParam(value = "temperature", required = false) Double temperature
    ) {
        ChatClient chatClient = buildChatClient(temperature, null);
        SseEmitter emitter = new SseEmitter(60_000L); // 超时时间60秒

        // 使用 Fluent API 构建请求，避免直接操作 Prompt 对象
        chatClient.prompt()
                .user(question) // 设置用户消息
                .stream()      // 发起流式请求
                .content()     // 获取文本流
                .subscribe(
                        content -> {
                            try {
                                // 发送 SSE 事件（含唯一ID和内容）
                                emitter.send(SseEmitter.event()
                                        .data(content)
                                        .id(UUID.randomUUID().toString())
                                        .build());
                            } catch (IOException e) {
                                emitter.completeWithError(e);
                            }
                        },
                        error -> {
                            emitter.completeWithError(error);
                        },
                        emitter::complete // 正常完成时关闭连接
                );

        // 连接生命周期回调
        emitter.onCompletion(() -> log.info("SSE连接完成"));
        emitter.onTimeout(() -> {
            log.warn("SSE连接超时");
            emitter.complete();
        });

        return emitter;
    }

    @Autowired
    private EnglishTranslateAIService englishTranslateAIService;

    @PostMapping("/translate")
    public SseEmitter translate(
            @RequestParam("content") String content,
            @RequestParam(value = "requirements", required = false) String[] requirements
    ) {
        return englishTranslateAIService.translateEnglishToChineseStream(content, requirements);
    }
}